package com.wlyy.bcwlw.sys;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.directwebremoting.annotations.RemoteProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.wlyy.bcwlw.base.BaseController;
import com.wlyy.bcwlw.common.annotation.SysLog;
import com.wlyy.bcwlw.common.exception.AuthenticationFailedException;
import com.wlyy.bcwlw.common.utils.CookieUtils;
import com.wlyy.bcwlw.common.utils.SecurityUtil;
import com.wlyy.bcwlw.sys.application.service.ApplicationService;
import com.wlyy.bcwlw.sys.user.dao.UserDAO;
import com.wlyy.bcwlw.sys.user.entity.UserDTO;
import com.wlyy.bcwlw.sys.user.entity.UserProfile;
import com.wlyy.bcwlw.sys.user.service.UserManageService;
/**
 * 
 * @ClassName. SecurityAuthenticationController
 * @Description. 用户登录控制器
 * @author zhangyang
 * @date 2015年8月31日 下午2:34:28
 * @version V1.0
 */
@RemoteProxy
@Controller
public class SecurityAuthenticationController extends BaseController{
	
	private static final Logger logger = LogManager.getLogger(SecurityAuthenticationController.class);
	@Autowired
	private ApplicationService applicationService;
	@Autowired
	private UserDAO userDAO;
	@Autowired
	private UserManageService userManageService;
	
	private static final int ONE_WEEKS_SECONDS = 7 * 24 * 3600;
	private static final String REMEMBER_CHOICE = "on";

	/***
	 * 
	* @Title. getForwardUrl
	* @Description. 重定向
	* @param url
	* @return String
	* @exception.
	 */
	private String getForwardUrl(String url) {
		return "redirect:" + url;
	}
	
	/**
	 * 
	* @Title. getRedirectLoginUrl
	* @Description. 获得可以重定向的登录地址，调用方式：response.sendRedirect
	* @param request
	* @return String
	* @exception.
	 */
	public String getRedirectLoginUrl(HttpServletRequest request) {
		String url = SecurityConst.getDefaultLoginFormUrlKey();
		return url.startsWith("http") ? url : (request.getContextPath() + url);
	}
	
	/**
	 * 
	* @Title. getRedirectIndexUrl
	* @Description. 获得可以重定向的主页地址，调用方式：response.sendRedirect
	* @param request
	* @return String
	* @exception.
	 */
	public String getRedirectIndexUrl(HttpServletRequest request) {
		String url = SecurityConst.getDefaultIndexFormUrlKey();
		return url.startsWith("http") ? url : (request.getContextPath() + url);
	}
	
	/**
	 * 
	* @Title. authentication
	* @Description. 用户登录/退出
	* @param authenticationTpye
	* @param request
	* @param response
	* @return
	* @throws Exception String
	* @e
	* xception.
	 */
	@RequestMapping(value = "/auth/login")
	@SysLog(description = "登录系统")
	public String authenticationLogin(HttpServletRequest request, HttpServletResponse response) {
		return authentication(SecurityConst.AUTHENTICATION_TPYE_LOGIN,request,response);
	}
	
	@RequestMapping(value = "/auth/logout")
	@SysLog(description = "退出系统")
	public String authenticationLogout(HttpServletRequest request, HttpServletResponse response) {
		return authentication(SecurityConst.AUTHENTICATION_TPYE_LOGOUT,request,response);
	}
	
	private String authentication(String authenticationTpye,HttpServletRequest request, HttpServletResponse response){
		if(logger.isDebugEnabled()){
			logger.debug("验证开始");
		}
		if (StringUtils.isBlank(authenticationTpye)) {
			try {
				throw new Exception("验证类型为空");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try{
			if(SecurityConst.AUTHENTICATION_TPYE_LOGIN.equals(authenticationTpye)){
				return login(request,response);
			}else if(SecurityConst.AUTHENTICATION_TPYE_LOGOUT.equals(authenticationTpye)){
				return logout(request,response);
			}
		}catch (AuthenticationFailedException e){
			if (logger.isDebugEnabled()) {
				logger.debug("验证失败");
			}
			String msg = null;
			try{
				msg = e.getMessage();
			}catch(Exception ex){
				msg = "登录失败，可能用户名或密码错误";
			}
			set(request, "message", msg);
			return "sys/login";
		}
		
		
		return null;
	}
	
	@RequestMapping({"/welcome", "/"})
	public String LoginIndex(HttpServletRequest request, HttpServletResponse response) throws Exception{
		
		Map<String, String> logininfo = autoLogin(request, response);
		
		try{
			if(StringUtils.isNotBlank(logininfo.get("redirectUrl"))){
				String redirectUrl = logininfo.get("redirectUrl");
				return redirectUrl;
			}
		}catch(AuthenticationFailedException e){
			if (logger.isDebugEnabled()) {
				logger.debug("验证失败");
			}
			set(request, "message", "登录失败，可能用户名或密码错误");
			return "sys/login";
		}
		
		return "sys/login";
	}
	
	
	private Map<String, String> autoLogin(HttpServletRequest request, HttpServletResponse response) throws Exception, AuthenticationFailedException {
		UserProfile up = SecurityFacade.getUserProfile();
		Map<String, String> resultMap = new HashMap<String, String>();
		if (up == null || up.isAnonymous()) {
			boolean isAutoLogin = "true".equals(CookieUtils.getCookie(request,SecurityConst.AQ_AUTHENTICATION_AUTOLOGIN_KEY));
			if (!isAutoLogin) {
				return resultMap;
			}
			String userId = CookieUtils.getCookie(request, SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY);
			if (StringUtils.isEmpty(userId)) {
				return resultMap;
			}
			String userIdSign = SecurityUtil.decodeCookieUserId(SecurityContextHolder.getUserDataFromCookie(request,SecurityConst.AQ_AUTHENTICATION_COOKIE_KEY_SIGN));
			if(!StringUtils.equalsIgnoreCase(userIdSign, userId)) {
				logger.info(userId + "与签名后的用户id["+ userIdSign +"]不一致，不允许自动登录");
				return resultMap;
			}
			UserDTO user = (UserDTO) userManageService.findById(userId);
			if (user == null) {
				return resultMap;
			}
			up = new UserProfile();
			up.setUserId(user.getUserId());
			up.setIp(SecurityUtil.getClientIP(request));
			up.setExplore(SecurityUtil.getClientExplorer(request));
		} else {
			up.setIp(SecurityUtil.getClientIP(request));
			up.setExplore(SecurityUtil.getClientExplorer(request));
		}
		resultMap.put("redirectUrl", authenticate(request, response, up, false, false));
		return resultMap;
	}
	
	/**
	 * 
	* @Title. authenticate
	* @Description. 用户信息验证
	* @param request
	* @param response
	* @param up
	* @return
	* @throws AuthenticationFailedException String
	* @exception.
	 */
	private String authenticate(HttpServletRequest request, HttpServletResponse response, UserProfile up,
			boolean isRememberLoginInfo, boolean modifyCookie) throws AuthenticationFailedException{
		up = userManageService.authenticate(up);
		userManageService.accessDecision(up);
		SecurityContextHolder.setLoginContextWithoutCookie(request, response, up);

		if (isRememberLoginInfo) {
			SecurityContextHolder.setLoginContextWithoutCookie(request, response, up);
			SecurityContextHolder.setLoginCookie(request, response, up, ONE_WEEKS_SECONDS);
			CookieUtils.setCookie(response, SecurityConst.AQ_AUTHENTICATION_AUTOLOGIN_KEY, "true", ONE_WEEKS_SECONDS);
		} else {
			if (modifyCookie) {
				SecurityContextHolder.setLoginContext(request, response, up);
			} else {
				SecurityContextHolder.setLoginContextWithoutCookie(request, response, up);
			}
		}
		return getForwardUrl(SecurityConst.getDefaultIndexFormUrlKey());
	}
	
	/**
	 * 
	* @Title. login
	* @Description. 登录
	* @param request
	* @param response
	* @return String
	* @exception.
	 */
	private String login(HttpServletRequest request, HttpServletResponse response){
		SecurityContextHolder.clearLoginContext(request);
		
		String userName = get(request,"userName");
		String password = get(request,"password");
		if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)){
			throw new AuthenticationFailedException();
		}
		boolean isRememberLoginInfo = false;
		String rememberMe = get(request,"rememberMe");
		if(REMEMBER_CHOICE.equals(rememberMe)){
			isRememberLoginInfo= true;
		}
		
		return authenticate(request,response,getUserProfile4Validate(request,userName,password),isRememberLoginInfo,true);
		
	}
	
	/**
	 * 
	* @Title. getUserProfile4Validate
	* @Description. 登录信息验证
	* @param request
	* @param username
	* @param password
	* @return UserProfile
	* @exception.
	 */
	private UserProfile getUserProfile4Validate(HttpServletRequest request, String username, String password) {
		String ip = SecurityUtil.getClientIP(request);
		String explore = SecurityUtil.getClientExplorer(request);

		if (logger.isDebugEnabled())
			logger.debug("The request from client is: " + ip);
		UserProfile up = new UserProfile();
		up.setUserName(username);
		up.setPassword(password);
		up.setIp(ip);
		up.setExplore(explore);
		return up;
	}
	
	/**
	 * 
	* @Title. logout
	* @Description. 退出
	* @param request
	* @param response
	* @return String
	* @exception.
	 */
	private String logout(HttpServletRequest request, HttpServletResponse response){
		
		SecurityContextHolder.clearUserLoginInfo(request, response);
		
		return getForwardUrl(SecurityConst.getDefaultLoginFormUrlKey());
	}
	
}
